package com.plm.mongo.crud;

import com.mongodb.Block;
import com.mongodb.MongoClient;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.Updates;
import com.plm.mongo.util.MongoUtil;
import org.bson.Document;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

import java.util.Arrays;
import java.util.List;

/**
 * @author Limi
 * @create 2018-12-31 18:24
 */
public class MongoCRUD {

    public static MongoClient mongoClient = null;

    @BeforeClass
    public static void beforeClass(){
        mongoClient = MongoUtil.getMongoClient();
    }

    @AfterClass
    public static void afterClass(){
        MongoUtil.closeMongoClient(mongoClient);
    }

    public MongoCollection getMongoCollection(String databaseName, String collectionName){
        //获取数据库
        MongoDatabase db = mongoClient.getDatabase(databaseName);
        //获取集合
        return db.getCollection(collectionName);
    }

    @Test
    public void testCreateOne(){
        MongoCollection<Document> collection = getMongoCollection("test", "students");
        //创建文档对象: 字段- 值
        Document students = new Document("name", "张三")
                .append("gender", "男")
                .append("age", 25);
        //使用内嵌文档
        List<String> sports = Arrays.asList("篮球","足球");
        List<String> movies = Arrays.asList("大话西游","喜剧之王","功夫");
        Document hobby = new Document("sports", sports)
               .append("movies", movies);

        students.put("hobby", hobby);

        //插入一条数据
        collection.insertOne(students);
    }

    @Test
    public void testCreateMany(){
        MongoCollection<Document> collection = getMongoCollection("test", "students");

        collection.insertMany(Arrays.asList(
                Document.parse("{name:'张三', gender:'男', age:22, hobby:{sports:['乒乓球', '羽毛球'], movies:['大上海','霸王别姬']}}"),
                Document.parse("{name:'小明', gender:'男', age:18, hobby:{sports:['网球', '排球'], movies:['小时代']}}"),
                Document.parse("{name:'小美', gender:'女', age:23, hobby:{sports:['跑步', '网球'], movies:['山楂树']}}")
        ));


    }

    @Test
    public void testFind(){
        MongoCollection<Document> collection = getMongoCollection("test", "students");

        //检索集合中的特定文档
        //FindIterable<Document> findIterable = collection.find(Filters.eq("name", "张三"));

        //使用嵌入式文档作为标准查询数据
        //FindIterable<Document> findIterable = collection.find(Filters.eq("hobby", Document.parse("{sports:['乒乓球', '羽毛球'], movies:['大上海','霸王别姬']}")));

        //使用带点表示法的嵌入式文档查询数据
        //FindIterable<Document> findIterable = collection.find(Filters.eq("hobby.sports", "羽毛球"));

        //使用运算符和复合查询读取数据
        // (lt,less than:小于，gt,greater than:大于，eq,equal：等于，lte:小于等于，gte：大于等于)
        //sort 1:升序 -1:降序
        //FindIterable<Document> findIterable = collection.find(Filters.lte("age", 38)).sort(Document.parse("{age:-1}"));

        //写一个隐含的AND查询
        //FindIterable<Document> findIterable = collection.find(Filters.and(
         //       Filters.lt("age", 38), Filters.eq("name", "张三")));

        //写一个“或”查询
        //FindIterable<Document> findIterable = collection.find(Filters.or(
         //       Filters.eq("age", 38), Filters.eq("name", "张三")));

        //使用“or”子句写一个隐含的AND查询
        FindIterable<Document> findIterable = collection.find(Filters.and(
                       Filters.eq("gender", "男"),
                       Filters.or(
                               Filters.lt("age", 25),Filters.regex("name", "^老"))));

        //实现com.mongodb.Block来打印迭代的结果
        Block<Document> printBlock = new Block<Document>() {
            @Override
            public void apply(Document document) {
                System.out.println(document.toJson());
            }
        };
        findIterable.forEach(printBlock);

    }

    /**
     * 使用分页查询
     */
    @Test
    public void testFindByPage(){
        MongoCollection collection = getMongoCollection("test", "students");
        int page = 2;
        int pageSize = 4;
        int totalSize = (int) collection.countDocuments();
        int totalPages = totalSize % pageSize == 0 ? totalSize / pageSize : totalSize / pageSize + 1;

        FindIterable<Document> iterable = collection.find()
                .skip((page - 1) * pageSize)
                .limit(pageSize)
                .sort(Document.parse("{age:1}"));

        MongoCursor<Document> mongoCursor = iterable.iterator();
        System.out.println("================第" + page + "页数记录，共" + totalPages + "页================");
        while (mongoCursor.hasNext()) {
            Document document = mongoCursor.next();
            System.out.println(document.toJson());
        }
        mongoCursor.close();
    }

    @Test
    public void testUpdate(){
        MongoCollection<Document> collection = getMongoCollection("test", "students");

        /*
        //更新一个文档
        collection.updateOne(
                Filters.eq("name", "张三"),
                Updates.combine(
                        Updates.set("address", "北京"), //新增属性
                        Updates.addToSet("hobby.movies", "功夫"), //往数组中添加元素
                        Updates.addToSet("hobby.sports", "网球"), //往数组中添加元素
                        Updates.unset("hobby.sport") //删除属性
                )
        );

        FindIterable<Document> documents = collection.find(Filters.eq("name", "张三"));
        */

        //更新多个文档
        collection.updateMany(
                Filters.eq("gender", "男"),
                Updates.combine(
                        Updates.set("address", "广州")
                )
        );

        FindIterable<Document> documents = collection.find(Filters.eq("gender", "男"));

        documents.forEach((Block<Document>) document -> System.out.println(document.toJson()));

    }

    /**
     * 修改并返回这个值
     */
    @Test
    public void testFindAndModify(){
        MongoCollection<Document> collection = getMongoCollection("test", "students");
        Document document = collection.findOneAndUpdate(
                Filters.eq("name", "张三"),
                Updates.set("address", "广州")
        );

        System.out.println(document.toJson());
    }

    @Test
    public void testDelete(){
        MongoCollection<Document> collection = getMongoCollection("test", "students");

        //根据条件删除数据
        //Document students = new Document("name", "张三");
        //collection.deleteOne(students);

        Document document = collection.findOneAndDelete(Filters.eq("name", "张三"));
        System.out.println(document.toJson());

    }

}
